package com.rocky.server;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.log4j.Logger;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.rocky.server.model.User;
import com.rocky.server.service.MessageService;
import com.rocky.server.service.UserService;
import com.rocky.server.util.GeoHash;

public class Handler implements Runnable {
	private static Logger logger = Logger.getLogger(Handler.class);
	private Socket socket;
	private BufferedWriter writer;
	private BufferedReader reader;
	private User user;
	
	private UserService userService = new UserService();
	private MessageService messageService = new MessageService();


	public Handler(final Socket socket) {
		this.socket = socket;
	}

	public void SendMsg(String Msg) {
		try {
			writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(), "UTF-8"));
			writer.write(Msg + "\n");
			writer.flush();
		} catch (IOException e) {
			closeHandler();
		}

	}

	private String ReceiveMsg() {
		try {
			reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
			String txt = reader.readLine();
			if (txt == null) {
				closeHandler();
			}
			return txt;
		} catch (IOException e) {
			closeHandler();
			return "";
		}
	}

	private void closeHandler() {
		try {
			if (socket != null) {
				System.out.println(socket.getInetAddress() + ":" + socket.getPort() + " Handler closed.");
				if(user!=null && Global.userHandlerList.get(user.getUserid())!=null){
					Global.userHandlerList.remove(user.getUserid());
					user = null;
				}
				socket.close();
			}
		} catch (IOException e) {
			logger.error(e.toString());
		}
	}

	public void run() {
		while (!socket.isClosed()) {
			System.out.println("New connection accepted " + socket.getInetAddress() + ":" + socket.getPort());
			String msg = ReceiveMsg();
			parser(msg);
			try {
				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		logger.debug(" disconnection.");
	}

	public void parser(String s) {
		if (s != null && s.length() > 0) {
			try {
				JSONArray jsaRequest = new JSONArray(s);
				int key = jsaRequest.getInt(0);
				switch(key){
				case 0:{
					//login
					String username = jsaRequest.getString(1);
					String password = jsaRequest.getString(2);
					JSONArray jsaResult = new JSONArray();
					if(userService.isValidate(username, password)){
						//登陆成功
						//返回好友列表（信息，状态，最后位置），未读信息数量
						this.user = Global.userList.get(username);
						Global.userHandlerList.put(user.getUserid(), this);
						jsaResult.put(0);
						jsaResult.put(true);
						jsaResult.put(this.user.getUsername());
						jsaResult.put(user.getNickname());
						jsaResult.put(user.getSex());
						jsaResult.put(user.getBirthday());
						jsaResult.put(user.getMood());
						List<String> tempFriendList = user.getFriendList();
						JSONArray jsaFriendList = new JSONArray();
						for(int i = 0 ; i < tempFriendList.size() ; i++){
							User friend = Global.userList.get(tempFriendList.get(i));
							JSONObject jsoFriend = new JSONObject();
							jsoFriend.put("userid", friend.getUserid());
							jsoFriend.put("username", friend.getUsername());
							jsoFriend.put("nickname", friend.getNickname());
							jsoFriend.put("birthday", friend.getBirthday());
							jsoFriend.put("sex", friend.getSex());
							jsoFriend.put("mood", friend.getMood());
							jsoFriend.put("face", (friend.getPhoto().length()>0?friend.getPhoto().get(0):""));
							jsaFriendList.put(jsoFriend);
						}
						jsaResult.put(jsaFriendList);
						jsaResult.put(messageService.getMessageList(user.getUserid()));
					}else{
						//密码错误
						jsaResult.put(0);
						jsaResult.put(false);
					}
					SendMsg(jsaResult.toString());
					//String deviceid = jsaRequest.getString(3);
					break;
				}
				case 1:{
					//通过username查找用户的详细信息
					String username = jsaRequest.getString(1);
					User tempUser = Global.userList.get(username);
					JSONArray jsaResult = new JSONArray();
					jsaResult.put(1);
					if(tempUser != null){
						jsaResult.put(true);
						jsaResult.put(tempUser.getUserid());
						jsaResult.put(tempUser.getNickname());
						jsaResult.put(tempUser.getSex());
						jsaResult.put(tempUser.getUsername());
						jsaResult.put(tempUser.getBirthday());
						jsaResult.put(tempUser.getMood());
					}else{
						jsaResult.put(false);
					}
					SendMsg(jsaResult.toString());
					break;
				}
				case 2:{
					//添加好友
					String firendname = jsaRequest.getString(1);
					User friend = Global.userList.get(firendname);
					JSONArray jsaResult = new JSONArray();
					jsaResult.put(2);
					if(friend != null){
						if(userService.addFirend(user.getUserid(), friend.getUserid())){
							Global.userList.get(user.getUsername()).getFriendList().add(firendname);
							jsaResult.put(true);
							jsaResult.put(friend.getUserid());
							jsaResult.put(friend.getUsername());
							jsaResult.put(friend.getNickname());
							jsaResult.put(friend.getSex());
							jsaResult.put(friend.getBirthday());
							jsaResult.put(friend.getMood());
							jsaResult.put((friend.getPhoto().length()>0?friend.getPhoto().get(0):""));
						}else{
							jsaResult.put(false);
							jsaResult.put("Data base error.");
						}
					}else{
						jsaResult.put(false);
						jsaResult.put("Dont have this user.");
					}
					SendMsg(jsaResult.toString());
					break;
				}
				case 3:{
					//发送消息
					String friendUsername = jsaRequest.getString(1);
					String msg = jsaRequest.getString(2);
					User friend = Global.userList.get(friendUsername);
					if(Global.userHandlerList.get(friend.getUserid())!=null){
						JSONArray jsaResult = new JSONArray();
						jsaResult.put(3);
						jsaResult.put(true);
						jsaResult.put(user.getUsername());
						jsaResult.put(user.getNickname());
						jsaResult.put(msg);
						Global.userHandlerList.get(friend.getUserid()).SendMsg(jsaResult.toString());
					}else{
						messageService.storeMessage(user.getUserid(), friend.getUserid(), msg,0);
					}
					break;
				}
				case 4:{
					//更新地理位置信息
					logger.debug("start store ["+user.getUsername()+"] location info.");
					String oldLocation_key = user.getLocation_key();
					logger.debug("old location key = " + oldLocation_key);
					double location_x = jsaRequest.getDouble(1);
					double location_y = jsaRequest.getDouble(2);
					logger.debug("new location x = " + location_x + " y = "+location_y);
					GeoHash geoHash = GeoHash.withBitPrecision(location_x, location_y,25) ;
					String location_key = geoHash.toBase32();
					logger.debug("new location key = " + location_key);
					user.setLocation_x(location_x);
					user.setLocation_y(location_y);
					user.setLocation_key(location_key);
					Global.userList.put(user.getUsername(), user);
					userService.updateLocation(user.getUserid(), location_x, location_y, location_key);
					
					if(oldLocation_key != null && !oldLocation_key.equals(location_key)){
						if(oldLocation_key!=null && !oldLocation_key.equals("")) {
							logger.debug("remove [" +user.getUsername() + "] from " + oldLocation_key);
							Global.GeoUserList.get(oldLocation_key).remove(user.getUserid());
						}
						if(!Global.GeoUserList.get(location_key).isEmpty()){
							logger.debug("now location key " + location_key + " is not null.");
							Global.GeoUserList.get(location_key).put(user.getUserid(), user.getUsername());
						}else{
							logger.debug("now location key " + location_key + " is null.");
							HashMap<Integer,String> newHashMap = new HashMap<Integer,String>();
							newHashMap.put(user.getUserid(), user.getUsername());
							Global.GeoUserList.put(location_key, newHashMap);
						}
					}
					if(oldLocation_key == null || (oldLocation_key!=null && oldLocation_key.equals(""))){
						if(!Global.GeoUserList.get(location_key).isEmpty()){
							logger.debug("now location key " + location_key + " is not null.");
							Global.GeoUserList.get(location_key).put(user.getUserid(), user.getUsername());
						}else{
							logger.debug("now location key " + location_key + " is null.");
							HashMap<Integer,String> newHashMap = new HashMap<Integer,String>();
							newHashMap.put(user.getUserid(), user.getUsername());
							Global.GeoUserList.put(location_key, newHashMap);
						}
					}
					//插入偶遇点，便于后台程序判断是否推送给其他设置了该偶遇点的用户
					if(location_key != null && !location_key.equals("")){
						if(Global.pointList.get(location_key) != null){
							if(!Global.pointList.get(location_key).contains(user.getUsername())){
								Global.pointList.get(location_key).add(user.getUserid());
							}
						}else{
							Set<Integer> tempUserList = new HashSet<Integer>();
							tempUserList.add(user.getUserid());
							Global.pointList.put(location_key, tempUserList);
						}
					}
					JSONArray jsaResult = new JSONArray();
					jsaResult.put(4);
					jsaResult.put(true);
					HashMap<Integer,String> tempHash = new HashMap<Integer,String>();
					HashMap<Integer, String> tempThisHash = Global.GeoUserList.get(geoHash.toBase32());
					if(tempThisHash != null && tempThisHash.size() > 0){
						tempHash.putAll(tempThisHash);
					}
					GeoHash[] adjacent = geoHash.getAdjacent();
					for(int i = 0 ; i < adjacent.length ; i++){
						HashMap<Integer, String> tempSubHash = Global.GeoUserList.get(adjacent[i].toBase32());
						if(tempSubHash != null && tempSubHash.size() > 0){
							tempHash.putAll(tempSubHash);
						}
					}
					tempHash.remove(user.getUserid());//移除自己
					Collection<String> tempGeoAllUserList = tempHash.values();
					JSONArray jsaUserList = new JSONArray();
					for(String tempUsername : tempGeoAllUserList){
						JSONObject jsoUser = new JSONObject();
						User tempUser = Global.userList.get(tempUsername);
						jsoUser.put("userid", tempUser.getUserid());
						jsoUser.put("username", tempUser.getUsername());
						jsoUser.put("nickname", tempUser.getNickname());
						jsoUser.put("birthday", tempUser.getBirthday());
						jsoUser.put("sex", tempUser.getSex());
						jsoUser.put("mood", tempUser.getMood());
						jsoUser.put("face", (tempUser.getPhoto().length()>0?tempUser.getPhoto().get(0):""));
						jsoUser.put("x", tempUser.getLocation_x());
						jsoUser.put("y", tempUser.getLocation_y());
						jsaUserList.put(jsoUser);
					}
					jsaResult.put(jsaUserList);
					SendMsg(jsaResult.toString());
					break;
				}
				case 5:{
					//更新个人心情、爱情宣言
					String loveword = jsaRequest.getString(1);
					double location_x = jsaRequest.getDouble(2);
					double location_y = jsaRequest.getDouble(3);
					String location_city = jsaRequest.getString(4);
					
					GeoHash geoHash = GeoHash.withBitPrecision(location_x, location_y,25) ;
					String location_key = geoHash.toBase32();
					JSONArray jsaResult = new JSONArray();
					jsaResult.put(5);
					if(messageService.storeLoveWord(user.getUserid(), loveword, location_key, location_city)){
						jsaResult.put(true);
					}else{
						jsaResult.put(false);
					}
					SendMsg(jsaResult.toString());
					break;
				}
				case 6:{
					//偶遇点设置
					double location_x = jsaRequest.getDouble(1);
					double location_y = jsaRequest.getDouble(2);
					String location = jsaRequest.getString(3);
					GeoHash geoHash = GeoHash.withBitPrecision(location_x, location_y,25) ;
					JSONArray jsaResult = new JSONArray();
					jsaResult.put(6);
					if(userService.addPoint(user.getUserid(), geoHash.toBase32(), location)){
						jsaResult.put(true);
					}else{
						jsaResult.put(false);
					}
					SendMsg(jsaResult.toString());
					break;
				}
				case 7:{
					//查询偶遇信息
					JSONArray jsa = messageService.getMetPointMessageList(user.getUserid());
					if(jsa.length() > 0){
						JSONArray jsaResult = new JSONArray();
						jsaResult.put(7);
						jsaResult.put(jsa);
						SendMsg(jsaResult.toString());
					}
					break;
				}
				case 8:{
					//查询爱情宣言信息
					int type = jsaRequest.getInt(1);// 0=附近 ，1 = 同城
					JSONArray loveWordList = new JSONArray();
					JSONArray jsaResult = new JSONArray();
					jsaResult.put(8);
					if(type == 0){
						double location_x = jsaRequest.getDouble(2);
						double location_y = jsaRequest.getDouble(3);
						GeoHash geoHash = GeoHash.withBitPrecision(location_x, location_y,25) ;
						loveWordList = messageService.getLoveWordByLocationKey(geoHash.toBase32());
						
					}else if(type == 1){
						String location_city = jsaRequest.getString(2);
						loveWordList = messageService.getLoveWordByCity(location_city);
					}
					if(loveWordList.length() > 0){
						jsaResult.put(loveWordList);
						SendMsg(jsaResult.toString());
					}
					break;
				}
				}
			} catch (JSONException e) {
				logger.error(e.toString());
			}
		}
	}
	
	public Socket getSocket(){
		return socket;
	}
}
